package com.zjcloud.jwgl.controller;

import com.zjcloud.common.core.domain.AjaxResult;
import com.zjcloud.jwgl.algorithm.OptimizedGeneticScheduler;
import com.zjcloud.jwgl.domain.AcLessonSchedule;
import com.zjcloud.jwgl.service.impl.OptimizedScheduleConflictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 优化的课程调度控制器
 * 1. 异步处理
 * 2. 响应式设计
 * 3. 高性能API
 */
@RestController
@RequestMapping("/academic/schedule")
public class OptimizedScheduleController {

    @Autowired
    private OptimizedGeneticScheduler scheduler;

    @Autowired
    private OptimizedScheduleConflictService conflictService;

    /**
     * 生成课表
     */
    @PostMapping("/generate")
    public AjaxResult generateSchedule(@RequestBody Map<String, Object> params) {
        try {
            // 参数验证
            if (!validateParams(params)) {
                return AjaxResult.error("参数不完整或格式错误");
            }

            // 异步生成课表
            CompletableFuture.runAsync(() -> {
                // 准备数据
                List<Long> courses = (List<Long>) params.get("courses");
                List<Long> teachers = (List<Long>) params.get("teachers");
                List<Long> classrooms = (List<Long>) params.get("classrooms");
                List<Long> classes = (List<Long>) params.get("classes");
                Map<String, Object> constraints = (Map<String, Object>) params.get("constraints");

                // 执行排课算法
                List<AcLessonSchedule> schedule = scheduler.schedule(
                    courses, teachers, classrooms, classes, constraints
                );

                // 更新时间槽占用情况
                for (AcLessonSchedule lesson : schedule) {
                    conflictService.updateTimeSlot(lesson, true);
                }
            });

            return AjaxResult.success("课表生成任务已启动");
        } catch (Exception e) {
            return AjaxResult.error("课表生成失败：" + e.getMessage());
        }
    }

    /**
     * 检查课程冲突（单个）
     */
    @PostMapping("/check-conflict")
    public AjaxResult checkConflict(@RequestBody AcLessonSchedule schedule) {
        try {
            Map<String, Object> result = conflictService.checkConflict(schedule);
            return AjaxResult.success(result);
        } catch (Exception e) {
            return AjaxResult.error("冲突检测失败：" + e.getMessage());
        }
    }

    /**
     * 批量检查课程冲突
     */
    @PostMapping("/batch-check-conflicts")
    public AjaxResult batchCheckConflicts(@RequestBody List<AcLessonSchedule> schedules) {
        try {
            List<Map<String, Object>> results = conflictService.batchCheckConflicts(schedules);
            return AjaxResult.success(results);
        } catch (Exception e) {
            return AjaxResult.error("批量冲突检测失败：" + e.getMessage());
        }
    }

    /**
     * 调整课程安排
     */
    @PutMapping("/adjust")
    public AjaxResult adjustSchedule(@RequestBody Map<String, Object> params) {
        try {
            AcLessonSchedule oldSchedule = (AcLessonSchedule) params.get("oldSchedule");
            AcLessonSchedule newSchedule = (AcLessonSchedule) params.get("newSchedule");

            // 检查新安排是否有冲突
            Map<String, Object> conflictResult = conflictService.checkConflict(newSchedule);
            if ((Boolean) conflictResult.get("hasConflict")) {
                return AjaxResult.error("调整后的课程安排存在冲突", conflictResult.get("conflicts"));
            }

            // 更新时间槽占用情况
            conflictService.updateTimeSlot(oldSchedule, false);
            conflictService.updateTimeSlot(newSchedule, true);

            return AjaxResult.success("课程调整成功");
        } catch (Exception e) {
            return AjaxResult.error("课程调整失败：" + e.getMessage());
        }
    }

    /**
     * 获取可用时间槽
     */
    @GetMapping("/available-slots")
    public AjaxResult getAvailableSlots(@RequestParam Map<String, Object> params) {
        try {
            Long teacherId = Long.parseLong((String) params.get("teacherId"));
            Long classroomId = Long.parseLong((String) params.get("classroomId"));
            Long classId = Long.parseLong((String) params.get("classId"));

            List<Map<String, Object>> availableSlots = new ArrayList<>();
            // 遍历所有时间槽
            for (int weekDay = 1; weekDay <= 5; weekDay++) {
                for (int lessonNo = 1; lessonNo <= 12; lessonNo++) {
                    AcLessonSchedule tempSchedule = new AcLessonSchedule();
                    tempSchedule.setTeacherId(teacherId);
                    tempSchedule.setClassroomId(classroomId);
                    tempSchedule.setClassId(classId);
                    tempSchedule.setWeekDay(weekDay);
                    tempSchedule.setLessonNo(lessonNo);

                    Map<String, Object> conflictResult = conflictService.checkConflict(tempSchedule);
                    if (!(Boolean) conflictResult.get("hasConflict")) {
                        Map<String, Object> slot = new HashMap<>();
                        slot.put("weekDay", weekDay);
                        slot.put("lessonNo", lessonNo);
                        availableSlots.add(slot);
                    }
                }
            }

            return AjaxResult.success(availableSlots);
        } catch (Exception e) {
            return AjaxResult.error("获取可用时间槽失败：" + e.getMessage());
        }
    }

    /**
     * 清理缓存
     */
    @DeleteMapping("/cache")
    public AjaxResult clearCache() {
        try {
            conflictService.clearCache();
            return AjaxResult.success("缓存清理成功");
        } catch (Exception e) {
            return AjaxResult.error("缓存清理失败：" + e.getMessage());
        }
    }

    /**
     * 验证参数
     */
    private boolean validateParams(Map<String, Object> params) {
        return params != null &&
               params.containsKey("courses") &&
               params.containsKey("teachers") &&
               params.containsKey("classrooms") &&
               params.containsKey("classes") &&
               params.containsKey("constraints");
    }
}